﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;

using Communication;

namespace Neuron.Cell
{
    public class PerceptronBackbone
    {
        private int _eventsOverAll = 0;
        private int _eventsThrownByReceptrons = 0;
        private int _eventsThrownByActrons = 0;
        private int _eventsThrownByPerceptrons = 0;
        //List<Perceptron> _network = null;
        Hashtable _network = null;

        private TCPIPSocket _server = null;

        public PerceptronBackbone()
        {
            this._server = new TCPIPSocket(9470, "SERVER");
            this._server.Connect();
            this._server.TCPTransmissionReceived += this.EventHandlerDataReceived;
            this._server.TCPServerNewClientConnected += this.EventHandlerNewClientConnected;

            this._network = new Hashtable();
        }

        public void DeletePerceptron(string name)
        {
            Perceptron p = (Perceptron)this._network[name];
            p.Shutdown();

            this._network.Remove(name);
        }
        
        public void ShutDown()
        {
            this._server.Disconnect();
        }

        public void EventHandlerDataReceived(string data)
        {
            string[] arrData = data.Split('|');
            if (arrData.Count() == 4)
            {
                switch (arrData[1].ToUpper())
                {
                    case "STIMULATE":
                        Perceptron p = (Perceptron)this._network[arrData[2]];
                        double value = Double.Parse(arrData[3].Replace('.', ','), System.Globalization.CultureInfo.InvariantCulture);
                        //Convert.ToDouble(arrData[2]);
                        p.stimulate(value);
                        /*
                        foreach(Perceptron p in this._network)
                        {
                            if (p != null)
                            {
                                if (p.Name == arrData[1])
                                {
                                    double value = Convert.ToDouble(arrData[2]);
                                    p.stimulate(value);
                                }
                            }
                        }
                        */
                        break;
                    default:
                        break;
                }
            }
        }

        private void EventHandlerNewClientConnected(string name)
        {
            string perceptronList = "";
            foreach (DictionaryEntry de in this._network)
            {
                Perceptron p = (Perceptron)de.Value;
                if (p.ActivationFunction == ActivationFunctionEnum.actor)
                {
                    perceptronList += "|ACTOR|" + p.Name;
                }
                if (p.ActivationFunction == ActivationFunctionEnum.receptor)
                {
                    perceptronList += "|RECEPTOR|" + p.Name;
                }
            }

            perceptronList = name + "|LIST" + perceptronList;
            //perceptronList = perceptronList.Trim('|');

            this._server.SendData(perceptronList);
        }

        /*
        public delegate void delegateCreatePerceptronCopy(Perceptron perceptronToClone);
        public event delegateCreatePerceptronCopy ClonePerceptron;

        private void EventHandlerClonePerceptron(Perceptron p)
        {
            if (ClonePerceptron != null)
            {
                ClonePerceptron(p);
            }
        }
        */

        public void add(Perceptron p)
        {
            p.FiredBy += this.CountEvents;
            this._network.Add(p.Name, p);
        }

        private void CountEvents(Perceptron p)
        {
            switch (p.ActivationFunction)
            {
                case ActivationFunctionEnum.actor:
                    this._eventsThrownByActrons += 1;
                    this._eventsOverAll += 1;
                    this._server.SendData("ALL|STIMULATE|ACTOR|" + p.Name + "|"  + Convert.ToString(p.HardLimit).Replace(',', '.') +  "|" + Convert.ToString(p.VectorOUT).Replace(',', '.'));
                    break;
                case ActivationFunctionEnum.receptor:
                    this._eventsThrownByReceptrons += 1;
                    this._eventsOverAll += 1;
                    break;
                default:
                    this._eventsThrownByPerceptrons += 1;
                    this._eventsOverAll += 1;
                    break;
            }
        }

        public int EventsOverAll
        {
            get { return this._eventsOverAll; }
        }

        public int EventsThrownByReceptrons
        {
            get { return this._eventsThrownByReceptrons; }
        }

        public int EventsThrownByActrons
        {
            get { return this._eventsThrownByActrons; }
        }

        public int EventsThrownByPerceptrons
        {
            get { return this._eventsThrownByPerceptrons; }
        }

        public void resetEventCounter()
        {
            this._eventsOverAll = 0;
            this._eventsThrownByActrons = 0;
            this._eventsThrownByPerceptrons = 0;
            this._eventsThrownByReceptrons = 0;
        }

        public Perceptron getPerceptronInstanceByName(string name)
        {
            return (Perceptron)this._network[name];
        }

    }
}
